/************************************************************
 * Project Name         [Thinking_In_Java]
 * File Name            [DatePanel.java]
 * Creation Date        [11-Jul-2014]
 * 
 * Copyright© ge.y.yang@gmail.com All Rights Reserved
 * 
 * Work hard, play harder, think big and keep fit
 ************************************************************/
package pkg_02_gui.clock_V2.ui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.GregorianCalendar;

import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.border.BevelBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.DefaultTableModel;

/**
 * 日期面板
 * 
 * @author 不落的太阳(Sean Yang)
 * @version 1.0
 * @since JDK 6
 * 
 */
public class DatePanel extends JPanel implements ActionListener, ChangeListener {

	private static final long serialVersionUID = -1627355538498555806L;

	/** 面板的宽度 */
	private final int width = 190;
	/** 面板的高度 */
	private final int height = 190;
	/** 显示年 */
	private JSpinner year = null;
	/** 显示月 */
	private JComboBox<String> mouth = null;
	/** 显示日期 */
	private JTable days = null;
	/** JTable的表格模型 */
	private DefaultTableModel tableModel = null;
	/** 日期对象 */
	private final GregorianCalendar calendar = CalendarPanel.calendar;

	public DatePanel() {
		setSize(width, height);
		setPreferredSize(new Dimension(width, height));
		setBorder(new TitledBorder(new LineBorder(Color.GRAY), "日期[D]"));
		setLayout(new FlowLayout(FlowLayout.CENTER, 7, 8));

		mouth = new JComboBox<String>();
		mouth.setPreferredSize(new Dimension(85, 20));
		initMouth();
		mouth.addActionListener(this);

		year = new JSpinner();
		year.setPreferredSize(new Dimension(75, 20));
		year.setValue(calendar.get(GregorianCalendar.YEAR));
		year.addChangeListener(this);

		days = new JTable();
		days.setShowGrid(false);
		days.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		days.setRowSelectionAllowed(false);
		days.setSelectionBackground(Color.blue);
		days.setSelectionForeground(Color.blue);
		tableModel = (DefaultTableModel) days.getModel();
		tableModel.addColumn("日");
		tableModel.addColumn("一");
		tableModel.addColumn("二");
		tableModel.addColumn("三");
		tableModel.addColumn("四");
		tableModel.addColumn("五");
		tableModel.addColumn("六");
		updateCalendar();

		JScrollPane scrollPane = new JScrollPane(days);
		scrollPane.setPreferredSize(new Dimension(170, 118));
		scrollPane.setBorder(new BevelBorder(BevelBorder.LOWERED));

		add(mouth);
		add(year);
		add(scrollPane);
	}

	/**
	 * 初始下拉框"月"的显示
	 */
	private void initMouth() {
		mouth.addItem("一月");
		mouth.addItem("二月");
		mouth.addItem("三月");
		mouth.addItem("四月");
		mouth.addItem("五月");
		mouth.addItem("六月");
		mouth.addItem("七月");
		mouth.addItem("八月");
		mouth.addItem("九月");
		mouth.addItem("十月");
		mouth.addItem("十一月");
		mouth.addItem("十二月");
		mouth.setSelectedIndex(calendar.get(GregorianCalendar.MONTH));
	}

	/**
	 * 获取当前year和当前mouth的日期所表示的二维数组
	 * 
	 * @param year
	 *            要设置的年
	 * @param mouth
	 *            要设置的月
	 * @return 返回当前年year和当前月mouth下所表示的二维数组
	 */
	private String[][] getCalendarTable(int year, int mouth) {
		calendar.set(GregorianCalendar.YEAR, year);
		calendar.set(GregorianCalendar.MONTH, mouth);
		// 获得当月最大天数
		int maxDay = calendar.getActualMaximum(GregorianCalendar.DAY_OF_MONTH);
		// 获的现在的日期
		int dayNo = calendar.get(GregorianCalendar.DAY_OF_MONTH);
		// 设置今天为1号
		calendar.set(GregorianCalendar.DAY_OF_MONTH, 1);
		// 获得1号是本周的星期几
		int firstDay = calendar.get(GregorianCalendar.DAY_OF_WEEK);
		calendar.set(GregorianCalendar.DAY_OF_MONTH, dayNo);
		// 下面这些是获取当前日期的核心算法
		String[][] array = new String[6][7];
		String[] a = new String[42];
		// 把array的全部元素填充为空格
		for (int i = 0; i < array.length; i++)
			Arrays.fill(array[i], "   ");

		// 向数组中填充当前year当前月的日期
		for (int i = 1; i <= maxDay; i++) {
			if (i == dayNo)
				a[firstDay - 2 + i] = "" + i + "*";
			else
				a[firstDay - 2 + i] = "" + i + " ";
		}
		// 把一维数组a转换为二维数组array
		for (int i = 0; i < 42; i++)
			array[i / 7][i % 7] = a[i];
		return array;
	}

	/**
	 * 更新日期的表格显示
	 */
	private void updateCalendar() {
		// 获取当前年
		int year = calendar.get(GregorianCalendar.YEAR);
		try {
			year = Integer.parseInt(this.year.getValue().toString());
		} catch (NumberFormatException e) {
			System.out.println("年转换错误: " + e.getMessage());
			year = calendar.get(GregorianCalendar.YEAR);
		}
		// 获取当前月
		int mouth = this.mouth.getSelectedIndex();
		String[][] array = getCalendarTable(year, mouth);

		// 向日期的表格中添加数据.
		// 首先将表格中的数据行数改为0.
		tableModel.setRowCount(0);
		for (int i = 0; i < array.length; i++)
			tableModel.addRow(array[i]);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		updateCalendar();

	}

	@Override
	public void stateChanged(ChangeEvent e) {
		updateCalendar();
	}

}
